package com.sugar.follow.up.module.business.service.userpatient;

import cn.hutool.core.collection.CollUtil;
import com.sugar.follow.up.framework.common.pojo.PageResult;
import com.sugar.follow.up.framework.common.util.object.BeanUtils;
import com.sugar.follow.up.module.business.controller.admin.userpatient.vo.UserPatientDoctorAllotReqVO;
import com.sugar.follow.up.module.business.controller.admin.userpatient.vo.UserPatientPageReqVO;
import com.sugar.follow.up.module.business.controller.admin.userpatient.vo.UserPatientRespVO;
import com.sugar.follow.up.module.business.controller.admin.userpatient.vo.UserPatientSaveReqVO;
import com.sugar.follow.up.module.business.controller.app.userpatient.vo.AppUserPatientSaveReqVO;
import com.sugar.follow.up.module.business.controller.app.userpatient.vo.AppUserPatientSimpleRespVO;
import com.sugar.follow.up.module.business.dal.dataobject.userpatient.UserPatientDO;
import com.sugar.follow.up.module.business.dal.dataobject.userpatienttags.UserPatientTagsDO;
import com.sugar.follow.up.module.business.dal.mysql.userpatient.UserPatientMapper;
import com.sugar.follow.up.module.business.service.userpatienttags.UserPatientTagsService;
import com.sugar.follow.up.module.business.util.AdminUserUtil;
import com.sugar.follow.up.module.system.api.user.AdminUserApi;
import com.sugar.follow.up.module.system.controller.admin.user.vo.user.UserSimpleRespVO;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static com.sugar.follow.up.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.sugar.follow.up.module.business.enums.ErrorCodeConstants.NO_PERMISSION;
import static com.sugar.follow.up.module.business.enums.ErrorCodeConstants.USER_PATIENT_NOT_EXISTS;

/**
 * 就诊人 Service 实现类
 *
 * @author Ysugar
 */
@Service
@Validated
public class UserPatientServiceImpl implements UserPatientService {

    @Resource
    private UserPatientMapper userPatientMapper;
    @Resource
    private UserPatientTagsService userPatientTagsService;

    @Resource
    private AdminUserApi adminUserApi;

    @Override
    public void updateUserPatient(UserPatientSaveReqVO updateReqVO) {
        // 校验存在
        Long id = updateReqVO.getId();
        validateUserPatientExists(id);

        String[][] tags = updateReqVO.getTags();
        if (Objects.nonNull(tags)) {
            // 先删除之前的
            userPatientTagsService.clear(id);

            for (String[] tag : tags) {
                if (Objects.nonNull(tag) && tag.length == 2) {
                    userPatientTagsService.createUserPatientTags(tag, id);
                }
            }
        }

        // 更新
        UserPatientDO updateObj = BeanUtils.toBean(updateReqVO, UserPatientDO.class);
        userPatientMapper.updateById(updateObj);
    }

    @Override
    public void userPatientDoctorAllot(UserPatientDoctorAllotReqVO doctorAllotReqVO) {
        userPatientMapper.update(UserPatientDO::getId, doctorAllotReqVO.getId()
                , UserPatientDO::getDoctorId, doctorAllotReqVO.getDoctorId(), UserPatientDO::getStatus, 1);
    }

    @Override
    public List<UserSimpleRespVO> getDoctors() {
        return adminUserApi.getAllDoctorUserList();
    }

    @Override
    public void deleteUserPatient(Long id) {
        // 校验存在
        validateUserPatientExists(id);
        // 删除
        userPatientMapper.deleteById(id);
    }

    @Override
    public void deleteUserPatientListByIds(List<Long> ids) {
        // 删除
        userPatientMapper.deleteByIds(ids);
    }

    @Override
    public UserPatientRespVO backGetUserPatient(Long id) {
        UserPatientDO userPatientDO = userPatientMapper.selectById(id);
        UserPatientRespVO respVO = BeanUtils.toBean(userPatientDO, UserPatientRespVO.class);

        if (Objects.nonNull(respVO)) {
            List<UserPatientTagsDO> allTags = userPatientTagsService.getAllByPatientId(id);
            respVO.setTags(allTags.stream().map(UserPatientTagsDO::getTag).collect(Collectors.toList()));
        }

        return respVO;
    }

    private UserPatientDO validateUserPatientExists(Long id) {
        UserPatientDO userPatientDO = userPatientMapper.selectById(id);
        if (userPatientDO == null) {
            throw exception(USER_PATIENT_NOT_EXISTS);
        }
        return userPatientDO;
    }

    @Override
    public PageResult<UserPatientRespVO> getUserPatientPage(UserPatientPageReqVO reqVO) {
        String tempTab = generatorSql(reqVO.getTags());

        Long doctorId = AdminUserUtil.isSuperAdmin();

        Long count = userPatientMapper.customSelectListCount(tempTab, reqVO.getName(), reqVO.getMobile(), reqVO.getIdCard(), reqVO.getIdCode(), reqVO.getPreferredPlan(),
                reqVO.getStatus(), reqVO.getRiskLevel(), reqVO.getDoctorName(), doctorId);

        if (count > 0) {

            Integer pageNo = reqVO.getPageNo();
            Integer pageSize = reqVO.getPageSize();

            int skipCount = (pageNo - 1) * pageSize;

            List<UserPatientRespVO> userPatients = userPatientMapper.customSelectList(tempTab, reqVO.getName(), reqVO.getMobile(), reqVO.getIdCard(), reqVO.getIdCode(),
                    reqVO.getPreferredPlan(), reqVO.getStatus(), reqVO.getRiskLevel(), reqVO.getDoctorName(), doctorId, skipCount, pageSize);

            return new PageResult<>(userPatients, count);
        }

        return new PageResult<>(Collections.emptyList(), 0L);
    }

    public String generatorSql(List<String[]> tags) {
        if (CollUtil.isNotEmpty(tags)){
            Map<String, List<String>> tagsGroupMap = tags
                    .stream()
                    .filter(tag -> tag.length == 2)
                    .collect(Collectors.groupingBy(tag -> tag[0], Collectors.mapping(tag -> tag[1], Collectors.toList())));

            StringBuilder sqlBuffer = new StringBuilder();

            Set<String> tagsGroupMapKeys = tagsGroupMap.keySet();
            // 获取总条件数量
            int size = tagsGroupMapKeys.size();

            boolean noFirst = false;

            for (String tagsGroupMapKey : tagsGroupMapKeys) {
                List<String> nowGroupTags = tagsGroupMap.get(tagsGroupMapKey);

                if (noFirst)
                    sqlBuffer.append(" union all ");
                List<String> conditions = nowGroupTags.stream().map(o -> String.join(",", tagsGroupMapKey, o)).collect(Collectors.toList());

                sqlBuffer.append("select bupt.patient_id from business_user_patient_tags bupt where bupt.deleted = 0 and bupt.tag in (");
                boolean conditionNoFirst = false;
                for (String condition : conditions) {
                    if (conditionNoFirst)
                        sqlBuffer.append(", ");
                    sqlBuffer.append(String.format("'%s'", condition));
                    conditionNoFirst = true;
                }
                sqlBuffer.append(")");
                noFirst = true;
            }

            return "select temp.patient_id, count(temp.patient_id) as total_count from (" + sqlBuffer + ") temp group by temp.patient_id having total_count >= " + size;
        }

        return null;
    }

    @Override
    public List<Long> execGeneratorSql(List<String[]> tags) {
        if (tags.isEmpty())
            return Collections.emptyList();

        return userPatientMapper.execSql(generatorSql(tags));
    }

    // ======================================== APP 接口 ========================================

    @Override
    public UserPatientDO getUserPatient(Long id) {
        return userPatientMapper.selectById(id);
    }

    @Override
    public void appCreateUserPatient(AppUserPatientSaveReqVO updateReqVO, Long userId) {
        UserPatientDO updateObj = BeanUtils.toBean(updateReqVO, UserPatientDO.class);
        updateObj.setUserId(userId);
        userPatientMapper.insert(updateObj);
    }

    @Override
    public void appUpdateUserPatient(AppUserPatientSaveReqVO updateReqVO, Long userId) {
        // 校验存在
        UserPatientDO userPatientDO = validateUserPatientExists(updateReqVO.getId());
        if (!userPatientDO.getUserId().equals(userId))
            throw exception(NO_PERMISSION);

        // 更新
        UserPatientDO updateObj = BeanUtils.toBean(updateReqVO, UserPatientDO.class);
        userPatientMapper.updateById(updateObj);
    }

    @Override
    public void appDeleteUserPatient(Long id, Long userId) {
        // 校验存在
        UserPatientDO userPatientDO = validateUserPatientExists(id);
        if (!userPatientDO.getUserId().equals(userId))
            throw exception(NO_PERMISSION);

        userPatientMapper.deleteById(id);
    }

    @Override
    public List<AppUserPatientSimpleRespVO> getUserPatientAllList(Long userId) {
        return userPatientMapper.getUserPatientAllList(userId);
    }

}